package ru.reaperoq.taskmanager.models

import jakarta.persistence.*
import org.hibernate.annotations.CreationTimestamp
import ru.reaperoq.taskmanager.dto.TaskResponse
import ru.reaperoq.taskmanager.toEpoch
import java.time.LocalDateTime
import java.util.*

@Entity(name = "tasks")
open class Task(
    @Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
    open val id: Long? = null,
    @Column(length = 256, nullable = false)
    open val title: String,
    @Column(nullable = false)
    val text: String = "",
    @Column(
        insertable = false,
        updatable = false,
        nullable = false,
        columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
    )
    @CreationTimestamp
    open val createdAt: LocalDateTime = LocalDateTime.now(),
    @Temporal(TemporalType.TIMESTAMP)
    @Column(nullable = false)
    open val timeStart: LocalDateTime,
    @Temporal(TemporalType.TIMESTAMP)
    open val timeEnd: LocalDateTime? = null,
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    open var status: Status = Status.STARTED,

    @Column
    open var sharedId: UUID? = null,

    @Column(nullable = false, updatable = false)
    open val visible: Boolean = true,

    @ManyToOne(fetch = FetchType.LAZY)
    open val parent: Task? = null,
    @OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.LAZY, mappedBy = "parent")
    open val subtasks: MutableSet<Task> = mutableSetOf(),


    @ManyToOne
    @JoinColumn(nullable = false, name = "author_id", updatable = false)
    open val author: User,
    @ManyToOne
    @JoinColumn(name = "list_id")
    open val list: TaskList? = null,

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(
        name = "tasks_to_tags",
        joinColumns = [JoinColumn(name = "tag_id", referencedColumnName = "id")],
        inverseJoinColumns = [JoinColumn(name = "task_id", referencedColumnName = "id")]
    )
    open val tags: MutableSet<Tag> = mutableSetOf(),

    @ManyToMany
    @JoinTable(
        name = "files_to_tasks",
        joinColumns = [(JoinColumn(name = "task_id", referencedColumnName = "id"))],
        inverseJoinColumns = [(JoinColumn(name = "file_id", referencedColumnName = "id"))],
    )
    val files: MutableSet<File> = mutableSetOf(),

    ) {
    enum class Status {
        STARTED, IN_PROGRESS, COMPLETED
    }

    @PrePersist
    fun onInsert() {

    }

    fun toResponse(): TaskResponse = TaskResponse(
        id = this.id!!,
        title = this.title,
        createdAt = this.createdAt.toEpoch(),
        timeStart = this.timeStart.toEpoch(),
        timeEnd = this.timeEnd?.toEpoch(),
        parentId = this.parent?.id,
        authorId = this.author.id!!,
        listId = this.list?.id,
        subtasks = this.subtasks.map { it.toResponse() },
        tags = this.tags.map {
            it.toResponse()
        },
        fileIds = this.files.map {
            it.id!!
        },
        status = this.status.name,
    )
}